<html>
<head>
<title>Test</title>
<script src="jsunit/app/jsUnitCore.js"></script>
<script src='MockFun.js'></script>
<script>
/*
 * Test Fixture
 */
function heavyFunction() {
  return 1;
}

function anotherHeavyFunction() {
	return 1.5;
}

var __orig__ = null;

function setUp() {
		__orig__ = heavyFunction;
}

function tearDown() {
	heavyFunction = __orig__;	
}

/*
 * Tests 
 */
function testShouldReturnTheValueSpecified(){			
	var m = mock('heavyFunction').thenReturn(2);
	assertEquals(2, heavyFunction());
	m.verify();
}

function testCouldReturnAStringValue() {
	var m = mock('heavyFunction').thenReturn('whatever');
	assertEquals('whatever', heavyFunction());			  		
	m.verify();
}

function testCouldReturnAStringIncluedSpace() {
	var m = mock('heavyFunction').thenReturn('a string');
	assertEquals('a string', heavyFunction());
	m.verify();			  		
}

function testShouldRenewHoldingOfOriginalFunWhenUseThenReturn() {
	var m = mock('heavyFunction').thenReturn(2);
	assertNotUndefined(heavyFunctionRemainInvokedTimes);
	
	m.renew();
	
	assertEquals(1, heavyFunction());  
	// remain the function, don't delete it
	assertFalse(typeof heavyFunctionRemainInvokedTimes == 'undefined');
}

function testShouldMockMultipleFunctions() {
	var m1 = mock('heavyFunction').thenReturn(2);
	var m2 = mock('anotherHeavyFunction').thenReturn(3);
	
	assertEquals(2, heavyFunction());
	assertEquals(3, anotherHeavyFunction());
	
	m1.renew();
	m2.renew();
	
	assertEquals(1, heavyFunction());
	assertEquals(1.5, anotherHeavyFunction());
}

function testShouldVerifyFailedIfInvokeMoreThanOnce() {
	var m = mock('heavyFunction').thenReturn(2);
	
	try { 
  	heavyFunction();
		heavyFunction(); 
		m.verify();
		fail('Counld not invoked twice.'); 
	} catch(expectationError) {
		assertEquals('ExpectationError', expectationError.name);
	}
}

function testShouldVerifyFailedIfNoInvoke() {
	var m = mock('heavyFunction').thenReturn(2);			  	
	try { 				
		m.verify();	
		fail('Should verify failed.');
	} catch(expectationError) {
		assertEquals('ExpectationError', expectationError.name);	
	}	  	
}

function testVerifyMultiInvalidMockFunctions() {
	var m1 = mock('heavyFunction').thenReturn(2);
	var m2 = mock('anotherHeavyFunction').thenReturn(3);
	
	heavyFunction();
	heavyFunction();
	
	try { 				
		m1.verify();	
		fail('Should verify failed.');
	} catch(expectationError) {
		assertEquals('ExpectationError', expectationError.name);	
	}	  
	
	try { 				
		m2.verify();	
		fail('Should verify failed.');
	} catch(expectationError) {
		assertEquals('ExpectationError', expectationError.name);	
	}	  
}

function testVerifyMultiValidMockFunctions() {
	var m1 = mock('heavyFunction').thenReturn(2);
	var m2 = mock('anotherHeavyFunction').thenReturn(3);
	
	heavyFunction();
	anotherHeavyFunction();
	
	m1.verify();
	m2.verify();
}

function testVerifyOneValidAndOneInvalidFunctions() {
	var m1 = mock('heavyFunction').thenReturn(2);
	var m2 = mock('anotherHeavyFunction').thenReturn(3);
	
	heavyFunction();
	
	m1.verify();
	
	try { 				
		m2.verify();	
		fail('Should verify failed.');
	} catch(expectationError) {
		assertEquals('ExpectationError', expectationError.name);	
	}	
}

function testExpectInvokedMoreThanOnce() {
	var m = mock('heavyFunction').expect(2);
	assertEquals(2, heavyFunctionRemainInvokedTimes);
	heavyFunction();
	heavyFunction();
	
	m.verify();
}

function testShouldFailedIfInvokeTimesLessThanExpectation() {
	var m = mock('heavyFunction').expect(2);
	heavyFunction();
	
	try { 				
		m.verify();	
		fail('Should verify failed.');
	} catch(expectationError) {
		assertEquals('ExpectationError', expectationError.name);	
	}	
}

function testShouldFailedIfInvokeTimesMoreThanExpectation() {
	var m = mock('heavyFunction').expect(2);
	heavyFunction();
	heavyFunction();
	heavyFunction();
	
	try { 				
		m.verify();	
		fail('Should verify failed.');
	} catch(expectationError) {
		assertEquals('ExpectationError', expectationError.name);	
	}	
}

function testShouldRenewHoldingOfOriginalFunWhenUseThenReturn() {
	var m = mock('heavyFunction').expect(2);
	assertNotUndefined(heavyFunctionRemainInvokedTimes);
	assertEquals(2, heavyFunctionRemainInvokedTimes);
	
	m.renew();
	
	assertEquals(1, heavyFunction());
	assertTrue(typeof heavyFunctionRemainInvokedTimes == 'undefined');
}

function testMockUndefinedFunction() {
	assertTrue(typeof undefinedFun == "undefined");
	var m = mock('undefinedFun').expect(1);
	assertNotUndefined(undefinedFun);
	
	undefinedFun();
	
	m.verify();
	m.renew();
	assertTrue(typeof undefinedFun == 'undefined');
}

function testReturnMultiValues() {
	var m = mock('heavyFunction').thenReturn(1, 2, 3);
	assertEquals(3, heavyFunctionRemainInvokedTimes);
	assertEquals(1, heavyFunction());
	assertEquals(2, heavyFunction());
	assertEquals(3, heavyFunction());	
	m.verify();
	
	try { 				
		heavyFunction();
		m.verify();
		fail('Should verify failed.');
	} catch(expectationError) {
		assertEquals('ExpectationError', expectationError.name);	
	}
	
	m.renew();	
	assertEquals(1, heavyFunction());
}

</script>
</head>
	
<body/>
</html>